﻿#include "treedata.h"

Tree::Tree(){
    genderCount.insert("男", 0);
    genderCount.insert("女", 0);

    root = 0;
    MaxID = 0;
}

//从hash表获取该键值对对应值
TreeNode* Tree::getValueFromID(int id){
    return idHash.value(id);
}

//从txt导入
bool Tree::inputDataFromFile(QString curFilePath){
    //打开文件
    QFile file(curFilePath);
    if(!file.open(QIODevice::ReadWrite | QIODevice::Text)){
        qDebug()<<"File Open Failed";
        return false;
    }
    //逐行读取
    QTextStream stream(&file);
    QString line_in;
    QStringList line_get;
    line_in = stream.readLine();
    if(line_in.isEmpty()){
        return false;
    }
    line_get = line_in.split("%");
    MaxID = line_get.at(0).toInt();

    line_in = stream.readLine();
    line_get = line_in.split("%");
    if(line_in.isEmpty()){
        return false;
    }
    //获取该行信息
    int id = line_get.at(0).toInt();
    QString name = line_get.at(1);
    QString birthplace = line_get.at(2);
    QString gender = line_get.at(3);
    double stature = line_get.at(4).toDouble();
    QString job = line_get.at(5);
    QString edubg = line_get.at(6);
    QString birthday = line_get.at(7);
    QString deathday = line_get.at(8);
    QString highestjob = line_get.at(9);
    QString lifetime = line_get.at(10);

    //添加该行到树上
    TreeNode* node = nullptr;
    node = new TreeNode();
    node -> ID = id;
    node -> Name = name;
    node -> Birthplace = birthplace;
    node -> Gender = gender;
    node -> Stature = stature;
    node -> Job = job;
    node -> EduBg = edubg;
    node -> Birthday = birthday;
    node -> Deathday = deathday;
    node -> HighestJob = highestjob;
    node -> LifeTime = lifetime;
    node -> FatherNode = nullptr;
    node -> PartnerNode = nullptr;

    genderCount[gender]++;
    idHash.insert(node->ID, node);
    eduBgHash.insert(node->EduBg, node->ID);
    birthdayHash.insert(node->Birthday, node->ID);
    deathdayHash.insert(node->Deathday, node->ID);

    //确定为根节点
    root = node->ID;
    while(!stream.atEnd())
    {
        line_in = stream.readLine();
        line_get = line_in.split("%");

        //获取该行信息
        int id = line_get.at(0).toInt();
        QString name = line_get.at(1);
        QString birthplace = line_get.at(2);
        QString gender = line_get.at(3);
        double stature = line_get.at(4).toDouble();
        QString job = line_get.at(5);
        QString edubg = line_get.at(6);
        QString birthday = line_get.at(7);
        QString deathday = line_get.at(8);
        QString highestjob = line_get.at(9);
        QString lifetime = line_get.at(10);
        int fatherID = line_get.at(11).toInt();
        int partnerID = line_get.at(12).toInt();

        //添加该行到树上
        node = new TreeNode();
        node -> ID = id;
        node -> Name = name;
        node -> Birthplace = birthplace;
        node -> Gender = gender;
        node -> Stature = stature;
        node -> Job = job;
        node -> EduBg = edubg;
        node -> Birthday = birthday;
        node -> Deathday = deathday;
        node -> HighestJob = highestjob;
        node -> LifeTime = lifetime;
        if(fatherID>0){
            node -> FatherNode = idHash.value(fatherID);
            node -> FatherNode -> SonList.append(id);
        }
        else{
            node->FatherNode = nullptr;
        }
        if(partnerID>0){
            if(idHash.value(partnerID)!=nullptr){
                node->PartnerNode = idHash.value(partnerID);
                node->PartnerNode->PartnerNode = node;
            }
        }else{
            node->PartnerNode = nullptr;
        }
        //添加改行到键值对
        genderCount[gender]++;
        idHash.insert(node->ID, node);
        eduBgHash.insert(node->EduBg, node->ID);
        birthdayHash.insert(node->Birthday, node->ID);
        deathdayHash.insert(node->Deathday, node->ID);
    }
    file.close();
    return true;
}

//添加操作
void Tree::addValue(int FatherID, int PartnerID, QStringList Data){
    QString name = Data.at(0);
    QString birthplace = Data.at(1);
    QString gender = Data.at(2);
    double stature = Data.at(3).toDouble();
    QString job = Data.at(4);
    QString edubg = Data.at(5);
    QString birthday = Data.at(6);
    QString deathday = Data.at(7);
    QString highestjob = Data.at(8);
    QString lifetime = Data.at(9);

    genderCount[gender]++;

    //新建节点
    TreeNode* node;
    node = new TreeNode();
    node -> ID = ++ MaxID;
    node -> Name = name;
    node -> Birthplace = birthplace;
    node -> Gender = gender;
    node -> Stature = stature;
    node -> Job = job;
    node -> EduBg = edubg;
    node -> Birthday = birthday;
    node -> Deathday = deathday;
    node -> HighestJob = highestjob;
    node -> LifeTime = lifetime;
    if(FatherID > 0){
        node -> FatherNode = idHash.value(FatherID);//
        node -> FatherNode -> SonList.append(node->ID);
    }
    else{
        node->FatherNode = nullptr;
    }
    if(PartnerID>0){
        node -> PartnerNode = idHash.value(PartnerID);
        node->PartnerNode->PartnerNode = node;
    }
    else{
        node->PartnerNode = nullptr;
    }

    if(FatherID<0&&PartnerID<0){
        root = node->ID;
    }
    //添加该行到键值对

    idHash.insert(node->ID, node);
    eduBgHash.insert(node->EduBg, node->ID);
    birthdayHash.insert(node->Birthday, node->ID);
    deathdayHash.insert(node->Deathday, node->ID);

    qDebug()<<root<<node->ID;
}

//修改操作
void Tree::updateValue(int id, QStringList Data){
    //获取各项信息
    QString name = Data.at(0);
    QString birthplace = Data.at(1);
    QString gender = Data.at(2);
    double stature = Data.at(3).toDouble();
    QString job = Data.at(4);
    QString edubg = Data.at(5);
    QString birthday = Data.at(6);
    QString deathday = Data.at(7);
    QString highestjob = Data.at(8);
    QString lifetime = Data.at(9);

    //将其更新到该节点上
    TreeNode* node = idHash.value(id);
    node -> Name = name;
    node -> Birthplace = birthplace;
    if(node->Gender != gender){
        genderCount[node->Gender]--;
        genderCount[gender]++;
        node->Gender = gender;
    }
    node -> Stature = stature;
    node -> Job = job;
    if(node->EduBg != edubg){
        eduBgHash.remove(node->EduBg, node->ID);
        eduBgHash.insert(edubg, node->ID);
        node->EduBg = edubg;
    }
    if(node->Birthday != birthday){
        eduBgHash.remove(node->Birthday, node->ID);
        eduBgHash.insert(birthday, node->ID);
        node->Birthday = birthday;
    }
    if(node->Deathday != deathday){
        eduBgHash.remove(node->Deathday, node->ID);
        eduBgHash.insert(deathday, node->ID);
        node->Deathday = deathday;
    }
    node -> Birthday = birthday;
    node -> Deathday = deathday;
    node -> HighestJob = highestjob;
    node -> LifeTime = lifetime;
}

//删除操作
QList<int> Tree::deleteValue(int id)
{
    //获取该节点指针
    QList<int> deletedIdList;
    TreeNode* node = idHash.value(id);
    //将其父亲的儿子列表中的该人删去
    if(node->FatherNode!=nullptr){
        node -> FatherNode -> SonList.removeOne(id);
    }
    //将其以及其后代删去
    QQueue<TreeNode*> needToBeDeleted;
    needToBeDeleted.enqueue(node);
    while (!needToBeDeleted.isEmpty()) {
        node = needToBeDeleted.dequeue();
        deletedIdList.append(node->ID);
        if(node->Gender=="男"){
            for(int i: node->SonList){
                needToBeDeleted.enqueue(idHash.value(i));
            }
            if(node->PartnerNode!=nullptr){
                deletedIdList.append(node->PartnerNode->ID);
                idHash.remove(node->PartnerNode->ID);
                birthdayHash.remove(node->PartnerNode->Birthday, node->PartnerNode->ID);
                deathdayHash.remove(node->PartnerNode->Deathday, node->PartnerNode->ID);
                eduBgHash.remove(node->PartnerNode->EduBg, node->PartnerNode->ID);
                genderCount["女"]--;
                delete node->PartnerNode;
            }
        }
        else {
            if(node->PartnerNode!=nullptr){
                node->PartnerNode->PartnerNode=nullptr;
            }
        }


        idHash.remove(node->ID);
        birthdayHash.remove(node->Birthday, node->ID);
        deathdayHash.remove(node->Deathday, node->ID);
        eduBgHash.remove(node->EduBg, node->ID);
        genderCount[node->Gender]--;
        delete node;
    }

    if(id == root){
        root = -1;
    }
    return deletedIdList;
}

//关键字查询操作
QList<int> Tree::searchKW(QString input, QString information)
{
    //建立空容器
    QList<int> get_ID;
    //对所有族谱成员通过键值对遍历
    //姓名
    QHash<int, TreeNode*>::iterator i;

    if(information == "姓名")
    {
        for(i = idHash.begin(); i != idHash.end(); i++)
        {
            if(i.value() != NULL)
            {
                TreeNode* p;
                p = i.value();
                QString str = p -> Name;
                if(str.contains(input, Qt::CaseSensitive))
                    get_ID.append(i.key());
            }
        }
    }
    else if(information == "出生地")
    {
        for(i = idHash.begin(); i != idHash.end(); i++)
        {
            if(i.value() != NULL)
            {
                TreeNode* p;
                p = i.value();
                QString str = p -> Birthplace;
                if(str.contains(input, Qt::CaseSensitive))
                    get_ID.append(i.key());
            }
        }
    }
    else if(information == "死亡日期")
    {
        get_ID =  deathdayHash.values(input);
    }
    else if(information == "出生日期")
    {
        get_ID = birthdayHash.values(input);
    }
    else if(information == "学历")
    {
        get_ID = eduBgHash.values(input);
    }
    else if(information == "职业")
    {
        for(i = idHash.begin(); i != idHash.end(); i++)
        {
            if(i.value() != NULL)
            {
                TreeNode* p;
                p = i.value();
                QString str = p -> Job;
                if(str.contains(input, Qt::CaseSensitive))
                    get_ID.append(i.key());
            }
        }
    }
    else if(information == "最高职业")
    {
        for(i = idHash.begin(); i != idHash.end(); i++)
        {
            if(i.value() != NULL)
            {
                TreeNode* p;
                p = i.value();
                QString str = p -> HighestJob;
                if(str.contains(input, Qt::CaseSensitive))
                    get_ID.append(i.key());
            }
        }
    }
    else if(information == "生平事迹")
    {
        for(i = idHash.begin(); i != idHash.end(); i++)
        {
            if(i.value() != NULL)
            {
                TreeNode* p;
                p = i.value();
                QString str = p -> LifeTime;
                if(str.contains(input, Qt::CaseSensitive))
                    get_ID.append(i.key());
            }
        }
    }
    return get_ID;
}

//查看操作
QStringList Tree:: readValue(int id)
{
    TreeNode* node = idHash.value(id);
    QStringList value;
    value.append(node->Name);
    value.append(node->Birthplace);
    value.append(node->Gender);
    value.append(QString("%1").arg(node->Stature));
    value.append(node->Job);
    value.append(node->EduBg);
    value.append(node->Birthday);
    value.append(node->Deathday);
    value.append(node->HighestJob);
    value.append(node->LifeTime);

    return value;
}

//关系查询操作
QList<int> Tree::searchRL(int ID, QString relative)
{
    //建立容器
    QList<int> relative_ID;

    //if(relative == 对应关系){
    //	if(该对应到的结点不是空结点)
    //		把该节点添加到容器中;
    //}

    TreeNode* node = idHash.value(ID);

    if(relative == "父亲")
    {
        if(node->FatherNode!=nullptr){
            relative_ID.append(node->FatherNode->ID);
        }
    }
    else if(relative == "伴侣")
    {
        if(node -> PartnerNode!= nullptr){
            relative_ID.append(node->PartnerNode->ID);
        }

    }
    else if(relative == "母亲")
    {
        if(node->FatherNode!=nullptr&&
                node->FatherNode->PartnerNode!=nullptr){
            relative_ID.append(node->FatherNode->PartnerNode->ID);
        }
    }
    else if(relative == "爷爷")
    {
        if(node->FatherNode!=nullptr&&
                node->FatherNode->FatherNode!=nullptr){
            relative_ID.append(node->FatherNode->FatherNode->ID);
        }
    }
    else if(relative == "奶奶")
    {
        if(node->FatherNode!=nullptr&&
                node->FatherNode->FatherNode!=nullptr&&
                node->FatherNode->FatherNode->PartnerNode!=nullptr){
            relative_ID.append(node->FatherNode->FatherNode->PartnerNode->ID);
        }
    }
    else if(relative == "儿子")
    {
        TreeNode* p = nullptr;
        for(int id: node->SonList){
            p = idHash.value(id);
            if(p->Gender=="男"){
                relative_ID.append(id);
            }
        }
    }
    else if(relative == "女儿")
    {
        TreeNode* p = nullptr;
        for(int id: node->SonList){
            p = idHash.value(id);
            if(p->Gender=="女"){
                relative_ID.append(id);
            }
        }
    }
    else if(relative == "孙子")
    {
        TreeNode* p;
        for(int i:node->SonList){
            p = idHash.value(i);
            for(int j:p->SonList){
                if(idHash.value(j) != NULL)
                    if(idHash.value(j) -> Gender == "男")
                        relative_ID.append(j);
            }
        }
    }
    else if(relative == "孙女")
    {
        TreeNode* p;
//        for(int i = 0; i < node->SonList.size(); i++)
//        {
//            int id = node->SonList.at(i);
//            p = idHash.value(id);
//            for(int j = 0; j < p->SonList.size(); j++)
//            {
//                id = p->SonList.at(j);
//                if(idHash.value(id) != NULL)
//                    if(idHash.value(id) -> Gender == "女")
//                        relative_ID.append(id);
//            }
//        }
        for(int i:node->SonList){
            p = idHash.value(i);
            for(int j:p->SonList){
                if(idHash.value(j) != NULL)
                    if(idHash.value(j) -> Gender == "女")
                        relative_ID.append(j);
            }
        }
    }
    else if(relative == "兄弟")
    {
        TreeNode* p, *q;
        if(node->FatherNode!=nullptr){
            q = node->FatherNode;
            for(int i:q->SonList){
                p = idHash.value(i);
                if(p->Gender=="男"){
                    relative_ID.append(i);
                }
            }
            relative_ID.removeOne(ID);
        }
    }
    else if(relative == "叔伯")
    {
        TreeNode* p,*q;
        if(node->FatherNode!=nullptr&&node->FatherNode->FatherNode!=nullptr){
            q = node->FatherNode->FatherNode;
            for(int i:q->SonList){
                p = idHash.value(i);
                if(p->Gender=="男"){
                    relative_ID.append(i);
                }
            }
            relative_ID.removeOne(node->FatherNode->ID);
        }
    }
    return relative_ID;
}

//清除操作
void Tree::clear(){
    if(root>0){
        deleteValue(root);
    }
    root = -1;
    MaxID = 0;
    idHash.clear();
    eduBgHash.clear();
    birthdayHash.clear();
    deathdayHash.clear();
    genderCount["男"]=0;
    genderCount["女"]=0;
}

//平均寿命
double Tree::getAvgLife()
{
    double all = 0;
    double count = 0;
    QHash<int, TreeNode*>::iterator i;
    for(i = idHash.begin(); i != idHash.end(); i++)
    {
        if(i.value() != NULL)
        {
            TreeNode* p;
            p = i.value();
            all += QDate::fromString(p->Birthday, "yyyy-MM-dd").daysTo(QDate::fromString(p->Deathday, "yyyy-MM-dd"))/365;
            count += 1;
        }
    }
    return all/count;
}

//男女比例
int Tree::getProportion()
{
    qDebug()<<genderCount["男"]<<genderCount["女"];
    qDebug()<<double(genderCount["男"])/double(genderCount["女"] + genderCount["男"]);
    return double(genderCount["男"])/double(genderCount["女"] + genderCount["男"])*100;
}

//平均身高
double Tree::getAvgStature()
{
    double all = 0;
    double count = 0;
    QHash<int, TreeNode*>::iterator i;
    for(i = idHash.begin(); i != idHash.end(); i++)
    {
        if(i.value() != NULL)
        {
            TreeNode* p;
            p = i.value();
            all += p -> Stature;
            count += 1;
        }
    }
    return all/count;
}

////平均学历
QString Tree::getAvgEdu()
{
    //各种学历有不同的加权值，计算最后的平均学历
    int count = eduBgHash.size();
    int num = eduBgHash.values("小学").size()*1
            + eduBgHash.values("初中").size()*2
            + eduBgHash.values("高中").size()*3
            + eduBgHash.values("高职").size()*4
            + eduBgHash.values("大学专科").size()*5
            + eduBgHash.values("大学本科").size()*6
            + eduBgHash.values("硕士研究生").size()*7
            + eduBgHash.values("博士研究生").size()*8;

    double avg = double(num)/count;
    if(avg < 1.5) return "小学";
    else if(avg < 2.5) return "初中";
    else if(avg < 3.5) return "高中";
    else if(avg < 4.5) return "高职";
    else if(avg < 5.5) return "大学专科";
    else if(avg < 6.5) return "大学本科";
    else if(avg < 7.5) return "硕士研究生";
    else return "博士研究生";
}

////平均家庭人口
double Tree::getAvgPerson()
{
    int count = 0;
    int num = 0;
    QHash<int, TreeNode*>::iterator i;
    for(i = idHash.begin(); i != idHash.end(); i++)
    {
        if(isFather(i.value()->ID)){
            if(i.value() != NULL)
            {
                TreeNode* p;
                p = i.value();
                num += p->SonList.size();

                if(p->FatherNode != NULL) num += 2;
            }
            count ++;
        }
    }
    return double(num/count + 2);
}

//关闭前把数据更新到文件
bool Tree::outputDataToFile(QString curFilePath)
{
    QFile file(curFilePath);
    file.open(QIODevice::WriteOnly | QIODevice::Text| QIODevice::Truncate);
    QTextStream stream(&file);
    stream<<MaxID<<endl;

    QList<int> idList = idHash.keys();
    std::sort(idList.begin(),idList.end());
    for(int i:idList)
    {
        TreeNode* node;
        node = idHash.value(i);
        int ID = node->ID;
        QString name = node -> Name;
        QString birthplace = node -> Birthplace;
        QString gender = node -> Gender;
        double stature = node -> Stature;
        QString job = node -> Job;
        QString edubg = node -> EduBg;
        QString birthday = node -> Birthday;
        QString deathday = node -> Deathday;
        QString highestjob = node -> HighestJob;
        QString lifetime = node -> LifeTime;
        int fatherID = node->FatherNode==nullptr? -1:node->FatherNode->ID;
        int partnerIdD = node->PartnerNode==nullptr? -1:node->PartnerNode->ID;

        QString str = QString(QString("%1").arg(ID) + "%" + name + "%" + birthplace + "%" + gender
                              + "%" + QString("%1").arg(stature) + "%" +job + "%" + edubg + "%" + birthday
                              + "%" + deathday + "%" + highestjob + "%" + lifetime+"%"+QString("%1").arg(fatherID)
                              +"%"+QString("%1").arg(partnerIdD));
        stream<<str<<endl;
    }
    file.close();
    return true;
}

QList<int> Tree::getALLID(){
    QList<int> idList = idHash.keys();
    std::sort(idList.begin(),idList.end());
    return idList;
}

bool Tree::isFather(int id){
    if(!idHash.value(id)->SonList.isEmpty()){
        return true;
    }
    else{
        return false;
    }
}

bool Tree::isMother(int id){
    TreeNode* tmp = idHash.value(id);
    if(tmp->PartnerNode!=nullptr&&tmp->Gender=="女"){
        return true;
    }
    else{
        return false;
    }
}
